<template>
<el-dialog class="history-order-dialog" :class="fullScreen ? 'full-screen' : ''" v-if="dialogVisible" :append-to-body="true" :visible.sync="dialogVisible" width="800px">
    <el-button-group>
      <el-button type="primary" @click.stop="handleFullScreen" :icon="fullScreen ? 'el-icon-full-screen' : 'el-icon-crop'"></el-button>
      <el-button type="primary" icon="el-icon-plus" @click="handleSvgPlusOrMinus('plus')"></el-button>
      <el-button type="primary" icon="el-icon-minus" @click="handleSvgPlusOrMinus('minus')"></el-button>
    </el-button-group>
    <div class="svg-continer">
      <svg id="svgcanvas" v-if="viewBox" ref="svgcanvas"
      xmlns="http://www.w3.org/2000/svg"
      xmlns:xlink="http://www.w3.org/1999/xlink"
      :width="svgWH.width"
      :height="svgWH.height"
      :viewBox="viewBox" version="1.1" v-html="svg">
      </svg>
    </div>
    <div class="canvas" ref="canvas"></div>
</el-dialog>
</template>
<script lang="ts">
import { Component, Vue, Ref, Prop } from 'vue-property-decorator'
import { commonAction } from '@/utils/common'
import { query as domQuery } from 'min-dom';
import { innerSVG } from 'tiny-svg';
import CustomModeler from '@/afterSales/businessConfig/bpmn/features/palette/customModeler'
import * as d3 from 'd3'
@Component({
  name: 'showBusFlow',
  components: {
  }
})
export default class ShowBusFlow extends Vue {
  [x: string]: any
  private dialogVisible = false
  private ids = [] as any
  private currentId = [] as any
  private percent = null as any
  private bpmnXml = ''
  private svg = ''
  private svgWH = {
    width: 752,
    height: 500
  }

  private fullScreen = false
  private viewBox = null as any
  private init () {
    this.svg = ''
    const canvas = this.$refs.canvas
    if (this.bpmnModeler) {
      this.bpmnModeler.destroy();
    }
    (this.$refs as any).canvas.innerHTML = ''
    // 建模
    this.bpmnModeler = new CustomModeler({
      container: canvas,
      height: 540
    })
    this.transformCanvas()
  }

  private handleFullScreen () {
    this.fullScreen = !this.fullScreen
    if (this.fullScreen) {
      this.svgWH = {
        height: window.innerHeight - 40,
        width: window.innerWidth - 40
      }
    } else {
      this.svgWH = {
        height: 500,
        width: 752
      }
    }
    this.init()
  }

  private transformCanvas () {
    const that: any = this;
    this.bpmnModeler.importXML(this.bpmnXml, (err) => {
      if (err) {
        console.log(err)
      } else {
        const canvas = that.bpmnModeler.get('canvas')
        canvas.zoom('fit-viewport', 'auto')
        that.setNodeColor(canvas)
      }
    })
  }

  private setNodeColor (canvas) {
    for (let i = 0; i < this.ids.length; i++) {
      if (this.ids[i].endTime) {
        canvas.addMarker(this.ids[i].activityId, 'nodeSuccess')
      } else {
        canvas.addMarker(this.ids[i].activityId, 'current-node')
      }
    }
    this.translateSvg()
  }

  private translateSvg () {
    const canvas = this.bpmnModeler.get('canvas')
    const contentNode = canvas.getDefaultLayer()
    const defsNode = domQuery('defs', canvas._svg);
    const contents = innerSVG(contentNode)
    const defs = defsNode ? '<defs>' + innerSVG(defsNode) + '</defs>' : '';
    this.bbox = contentNode.getBBox();
    this.viewBox = `${this.bbox.x} ${this.bbox.y} ${this.svgWH.width} ${this.svgWH.height}`
    this.svg = defs + contents;
    if (this.bpmnModeler) {
      this.bpmnModeler.destroy();
    }
    (this.$refs as any).canvas.innerHTML = ''
    this.$nextTick(() => {
      this.zoomimg()
    })
  }

  private handleSvgPlusOrMinus (type: string) {
    const el = (this.$refs as any).svgcanvas;
    if (type === 'plus') {
      d3.select(el).call(this.d3Zoom.scaleTo, (this.percent + 10) / 100);
    } else {
      d3.select(el).call(this.d3Zoom.scaleTo, (this.percent - 10) / 100);
    }
  }

  private get d3Zoom () {
    const that = this
    return d3
      .zoom()
      .scaleExtent([0.5, 3])
      .translateExtent([
        [-Infinity, -Infinity],
        [+Infinity, +Infinity]
      ])
      .on('zoom', (event) => {
        console.log(event);
        const transform = event.transform;
        this.percent = Math.round(transform.k * 100);
        this.transform = `translateX(${transform.x}px) translateY(${transform.y}px) scale(${transform.k})`;
        d3.select((that.$refs as any).svgcanvas)
          .selectAll('g.djs-group')
          .attr('transform', transform);
      });
  }

  private zoomimg () {
    const el = (this.$refs as any).svgcanvas;
    d3.select(el).call(this.d3Zoom);
  }

  public open (data: any) {
    this.dialogVisible = true;
    const getProcess = commonAction({ url: `/server-flow/action/definition/process?workModelId=${data.modelId}&orderId=${data.id}`, method: 'get' })
    const getActivities = commonAction({ url: `/server-flow/action/instance/activities?modelId=${data.modelId}&orderId=${data.id}`, method: 'get' })
    Promise.all([getProcess, getActivities]).then(([res1, res2]) => {
      if (res1.success && res2.success) {
        this.bpmnXml = res1.data.bpmn || ''
        this.ids = res2.data || []
        this.svgWH = {
          width: 752,
          height: 500
        }
        this.fullScreen = false
        this.svg = ''
        this.init()
      }
    })
  }
}
</script>
<style lang="stylus">
.full-screen {
  top: 0px !important;
  height: 100% !important;
  .el-dialog {
    width: 100% !important;
    height: 100% !important;
    margin-top: 0px !important;
    margin-bottom: 0px;
  }
}
.svg-div {
  transform-origin: left;
}
.current-node .djs-visual rect {
  stroke: #2ED47A !important;
  fill: #2ED47A !important;
}
.nodeSuccess .djs-visual> :nth-child(1) {
  stroke: #008BEE !important;
  fill: #fff !important;
}
</style>
